package check

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"

	"gitee.com/tuboyou/c2/request"
	"gitee.com/tuboyou/c2/u2"
)

// keycheck 校验
// vtype 类型
// name 名称
// key 校验类型
// exp 期望值
// val 实际值
func keycheck(vtype, key, action, exp, val string, hasEmpty bool, errList []error) []error {
	if hasEmpty && val == "" {
		return errList
	}
	switch vtype {
	case "Int8":
		fallthrough
	case "Int16":
		fallthrough
	case "Int32":
		fallthrough
	case "Int64":
		fallthrough
	case "uint":
		fallthrough
	case "uint8":
		fallthrough
	case "uint16":
		fallthrough
	case "uint32":
		fallthrough
	case "uint64":
		fallthrough
	case "int":
		intv, err := strconv.Atoi(val)
		if err != nil {
			errList = append(errList, errors.New(key+"校验"+val+"失败，实际值不是数字"))
			return errList
		}
		errList = checkInt(key, intv, exp, action, errList)
	case "float32":
		fallthrough
	case "float64":
		floatv, err := strconv.ParseFloat(val, 64)
		if err != nil {
			errList = append(errList, errors.New(key+"校验"+val+"失败，实际值不是数字"))
			return errList
		}
		errList = checkFloat(key, floatv, exp, action, errList)
	case "bool":
		boolv, err := strconv.ParseBool(val)
		if err != nil {
			errList = append(errList, errors.New(key+"校验"+val+"失败，实际值不是bool"))
			return errList
		}
		errList = checkBool(key, boolv, exp, action, errList)
	case "string":
		errList = checkString(key, val, exp, action, errList)
	}
	return errList

}

func checkString(key string, val string, exp string, action string, errlist []error) []error {
	exp = strings.Replace(exp, "\\n", "\n", -1)
	exp = strings.Replace(exp, "\\r", "\r", -1)
	exp = strings.Replace(exp, "\\t", "\t", -1)
	exp_num, nerr := strconv.Atoi(exp)

	switch action {
	case "eq":
		fallthrough
	case "Equal":
		fallthrough
	case "equal":
		if exp == val {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望："+exp+"，实际："+val))
		}
	case "leq":
		fallthrough
	case "lengthEqual":
		fallthrough
	case "len_equal":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) == exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "ne":
		fallthrough
	case "neq":
		fallthrough
	case "notequal":
		if exp != val {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "lneq":
		fallthrough
	case "lengthnotEqual":
		fallthrough
	case "len_notequal":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) != exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "lgt":
		fallthrough
	case "lengthgreaterthan":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) > exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}

	case "legt":
		fallthrough
	case "lgte":
		fallthrough
	case "lge":
		fallthrough
	case "lengthgreaterthanequal":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) >= exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}

	case "llt":
		fallthrough
	case "lengthlessthan":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) < exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "lelt":
		fallthrough
	case "llte":
		fallthrough
	case "lengthlessThanEqual":
		if nerr != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
		if len(val) <= exp_num {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}

	case "lbetween":
		fallthrough
	case "lbt":

		lexp := strings.Split(exp, ",")
		if len(lexp) != 2 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		lexp1, err := strconv.Atoi(lexp[0])
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		lexp2, err := strconv.Atoi(lexp[1])
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		if len(val) > lexp1 && len(val) < lexp2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于实际（"+strconv.Itoa(len(val))+"）"))
		}
	case "tgt":
		fallthrough
	case "timegreaterthan":

		t := u2.TimeFormat2timestamp(val, false)
		if t == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值("+val+")不是时间格式"))
		}
		t2 := u2.TimeFormat2timestamp(exp, false)
		if t2 == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值("+exp+")不是时间格式"))
		}
		if t > t2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于实际（"+val+"）"))
		}
	case "tge":
		fallthrough
	case "timegreaterthanequal":
		t := u2.TimeFormat2timestamp(val, false)
		if t == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值("+val+")不是时间格式"))
		}
		t2 := u2.TimeFormat2timestamp(exp, false)
		if t2 == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值("+exp+")不是时间格式"))
		}
		if t >= t2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于等于实际（"+val+"）"))
		}
	case "tlt":
		fallthrough
	case "timelessthan":
		t := u2.TimeFormat2timestamp(val, false)
		if t == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值("+val+")不是时间格式"))
		}
		t2 := u2.TimeFormat2timestamp(exp, false)
		if t2 == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值("+exp+")不是时间格式"))
		}
		if t < t2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）小于实际（"+val+"）"))
		}
	case "tle":
		fallthrough
	case "timelessthanequal":
		t := u2.TimeFormat2timestamp(val, false)
		if t == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值("+val+")不是时间格式"))
		}
		t2 := u2.TimeFormat2timestamp(exp, false)
		if t2 == -1 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值("+exp+")不是时间格式"))
		}
		if t <= t2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）小于等于实际（"+val+"）"))
		}
	case "igt":
		fallthrough
	case "intgreaterthan":
		intv, err := strconv.Atoi(val)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值不是数字"))
		}
		intv2, err := strconv.Atoi(exp)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值不是数字"))
		}
		if intv > intv2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于实际（"+val+"）"))
		}
	case "ige":
		fallthrough
	case "intgreaterthanequal":
		intv, err := strconv.Atoi(val)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值不是数字"))
		}
		intv2, err := strconv.Atoi(exp)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值不是数字"))
		}
		if intv >= intv2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于等于实际（"+val+"）"))
		}
	case "ilt":
		fallthrough
	case "intlessthan":
		intv, err := strconv.Atoi(val)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值不是数字"))
		}
		intv2, err := strconv.Atoi(exp)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值不是数字"))
		}
		if intv < intv2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）小于实际（"+val+"）"))
		}
	case "ile":
		fallthrough
	case "intlessthanequal":
		intv, err := strconv.Atoi(val)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值不是数字"))
		}
		intv2, err := strconv.Atoi(exp)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望值不是数字"))
		}
		if intv <= intv2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）小于等于实际（"+val+"）"))
		}
	case "ibt":
		fallthrough
	case "intbetween":
		lexp := strings.Split(exp, ",")
		if len(lexp) != 2 {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		lexp1, err := strconv.Atoi(lexp[0])
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		lexp2, err := strconv.Atoi(lexp[1])
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望比较数值,期望值为："+exp))
		}
		intv, err := strconv.Atoi(val)
		if err != nil {
			return append(errlist, errors.New(key+"校验"+action+"失败，实际值不是数字"))
		}
		if intv >= lexp1 && intv <= lexp2 {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望（"+exp+"）大于实际（"+val+"）"))
		}
	case "wi":
		fallthrough
	case "within":
		//整体匹配
		if u2.SliceHas(strings.Split(exp, ","), val, false) {
			return nil
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "wo":
		fallthrough
	case "without":
		//整体不匹配
		if !u2.SliceHas(strings.Split(exp, ","), val, false) {
			return nil
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "contain":
		fallthrough
	case "have":
		fallthrough
	case "contains":
		fallthrough
	case "has":
		//局部包含
		if u2.SliceBeContains(val, strings.Split(exp, ","), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "nc":
		fallthrough
	case "nh":
		fallthrough
	case "notcontain":
		fallthrough
	case "nothas":
		fallthrough
	case "nothave":
		fallthrough
	case "notcontains":
		//局部不包含
		if !u2.SliceBeContains(val, strings.Split(exp, ","), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "bc":
		fallthrough
	case "cb":
		fallthrough
	case "becontain":
		fallthrough
	case "containby":
		fallthrough
	case "containsby":
		fallthrough
	case "becontains":
		// 被包含
		if u2.SliceContains(strings.Split(exp, ","), val, false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "nbc":
		fallthrough
	case "ncb":
		fallthrough
	case "notbecontain":
		fallthrough
	case "notbecontains":
		fallthrough
	case "notcontainby":
		fallthrough
	case "notcontainsby":
		if !u2.SliceContains(strings.Split(exp, ","), val, false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "st":
		fallthrough
	case "sw":
		fallthrough
	case "startswtih":
		fallthrough
	case "startwith":
		if strings.HasPrefix(val, exp) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "nsw":
		fallthrough
	case "notstartswtih":
		fallthrough
	case "notstartwith":
		if !strings.HasPrefix(val, exp) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "ew":
		fallthrough
	case "ed":
		fallthrough
	case "endwith":
		fallthrough
	case "endswith":
		if strings.HasSuffix(val, exp) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "ned":
		fallthrough
	case "notendwith":
		fallthrough
	case "notendswith":
		if !strings.HasSuffix(val, exp) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
		}
	case "save":
		// 保存值
		// result:"save:xxx"
		request.GlobalMapmap[exp] = val
	case "type":
		// 类型校验
		if exp == "string" {
			return errlist
		} else {
			if exp == "bool" {
				_, err := strconv.ParseBool(val)
				if err != nil {
					return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
				}
			} else {
				if exp == "int" {
					_, err := strconv.Atoi(val)
					if err != nil {
						return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
					}
				} else {
					if exp == "float" {
						_, err := strconv.ParseFloat(val, 64)
						if err != nil {
							return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
						}
					} else {
						if exp == "time" {
							t := u2.TimeFormat2timestamp(val, false)
							if t == -1 {
								return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
							}
						} else {
							if exp == "url" {
								_, err := url.ParseRequestURI(val)
								if err != nil {
									return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
								}
							} else {
								if exp == "timestamp" {
									// 没啥用
									_, err := strconv.Atoi(val)
									if err != nil {
										return append(errlist, errors.New(key+"校验"+action+"失败，期望："+exp+"，实际："+val))
									}

								} else {
									return append(errlist, errors.New(key+"校验"+action+"失败，未知类型："+exp))

								}

							}
						}
					}
				}
			}
		}
	default:
		return append(errlist, errors.New(key+"校验失败，字符未知校验规则："+action))
	}
	return errlist
}

// CheckTag 校验
// valtype 字段类型
// key 字段名称
// val 字段值
// tag 标签值
// eg. result:"eq:1"
// eq/Equal/equal/等于/=/== val \n
// ne/neq/notequal val \n
// leq/lengthEqual/len_equal val \n
// lneq/lengthnotEqual/len_notequal val \n
// gt/greaterthan/> val \n
// egt/gte/ge/greaterthanequal/>= val \n
// lt/lessthan/< val \n
// elt/lte/lessThanEqual/<= val \n
// between/bt val,val
// wi/within val,val... \n
// wo/without val,val... \n
// contain/have/contains/has val,val... \n
// nc/nh/notcontain/notcontains/nothas/nothave/notcontains val,val... \n
// bc/cb/becontain/containby/containsby val,val... \n
// nbc/ncb/notbecontain/notcontainby/notcontainsby val,val... \n
// sw/startswtih/startwith val \n
// nsw/notstartswtih/notstartwith val \n
// ed/endwith/endswith val \n
// ned/notendwith/notendswith val \n
// save val
func checkTag(valtype string, key string, val interface{}, tag reflect.StructTag, errList []error) []error {

	tagmap, hasEmpty, e := tagGetValue(tag, key, "result")
	if e != nil {
		errList = append(errList, e)
		return errList
	}
	// log.Println("checkTag", valtype, key, tagmap)
	val2 := ""
	switch vv := val.(type) {
	case string:
		val2 = vv
	case int:
		val2 = strconv.Itoa(vv)
	case float64:
		val2 = strconv.FormatFloat(vv, 'f', 2, 64)
	case bool:
		val2 = strconv.FormatBool(vv)
	case nil:
		val2 = "nill"
	case json.Number:
		val2 = vv.String()
	default:
		errList = append(errList, errors.New(key+"：响应未知类型:"+fmt.Sprintf("%T", val)))
		return errList
	}
	for k, v := range tagmap {
		errList = keycheck(valtype, key, k, v, val2, hasEmpty, errList)
	}
	return errList

}

// tagGetValue 获取tag值
// tag 标签值
// key 字段名称
func tagGetValue(tag reflect.StructTag, key string, sep string) (map[string]string, bool, error) {
	tag_str := string(tag)
	tagmap := make(map[string]string)
	if sep == "" {
		sep = "result"
	}
	hasEmpty := false
	for _, v := range strings.Split(tag_str, " ") {
		// 判断符合条件的数据
		if strings.Contains(v, ":") && strings.HasPrefix(v, sep+":\"") && strings.HasSuffix(v, "\"") {
			// 获取有效数据
			lineTwo := v[2+len(sep) : len(v)-1]
			for _, line := range strings.Split(lineTwo, ";") {
				//tmpl 解析的单个值
				tmpl := strings.Split(line, ":")
				if tmpl[0] == "empty" {
					hasEmpty = true
					continue
				}
				if len(tmpl) == 2 {
					if len(tmpl[0]) == 0 {
						return tagmap, hasEmpty, errors.New(key + "校验格式错误，当前:yyy不正确，格式为 result:\"yyy:xxx\"")
					}

					tagmap[tmpl[0]] = tmpl[1]
				} else {
					if len(tmpl) == 1 {

						tagmap["eq"] = line
					} else {
						tagmap[tmpl[0]] = strings.Replace(line, tmpl[0]+":", "", 1)
					}
				}
			}
		}
	}
	return tagmap, hasEmpty, nil
}

// StructCheck 结构体校验
// key 字段名称
// val 字段值
// tag 标签值
// errList 错误列表
// func checkStruct(key string, val interface{}, tag reflect.StructTag, errList []error) []error {
// 	// errList = append(errList, errors.New(key+"校验失败,当前 struct 未开启校验校验规则"))
// 	// log.Println("checkStruct", key, val, tag)
// 	return errList
// }

// checkSlice 切片校验
// key 字段名称
// val 字段值
// tag 标签值 result:"eq:1"
// errList 错误列表
func checkSlice(key string, val int, tag reflect.StructTag, errList []error) []error {
	m, _, e := tagGetValue(tag, key, "list")
	if e != nil {
		errList = append(errList, e)
		return errList
	}
	for k, v := range m {
		errList = checkInt(key, val, v, k, errList)
	}
	return errList
	// errList = append(errList, errors.New(key+"校验失败,当前 slice 未开启校验校验规则"))

}

// checkInt 校验长度
// key 字段名称
// reslen 实际
// explen 期望
// action 校验规则
// errlist 错误列表
// 支持规则：leq/eq/neq/greaterthan/lessthan/gte/lte
func checkInt(key string, reslen int, explen string, action string, errlist []error) []error {
	switch action {
	case "between":
		fallthrough
	case "bt":
		lexp := strings.Split(explen, ",")
		if len(lexp) != 2 {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist
		}
		lexp1, err := strconv.Atoi(lexp[0])
		if err != nil {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist
		}
		lexp2, err := strconv.Atoi(lexp[1])
		if err != nil {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist
		}
		if reslen >= lexp1 && reslen <= lexp2 {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "wi":
		fallthrough
	case "within":
		//整体匹配
		if u2.SliceHas(strings.Split(explen, ","), strconv.Itoa(reslen), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望："+explen+"，实际："+strconv.Itoa(reslen)))
		}
	case "wo":
		fallthrough
	case "without":
		//整体不匹配
		if !u2.SliceHas(strings.Split(explen, ","), strconv.Itoa(reslen), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望："+explen+"，实际："+strconv.Itoa(reslen)))
		}
	}

	lexp, err := strconv.Atoi(explen)
	if err != nil {
		errlist = append(errlist, errors.New(key+"校验失败，期望值是数字,当前为："+explen))
		return errlist
	}
	switch action {
	case "leq":
		fallthrough
	case "eq":
		if reslen == lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）等于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "neq":
		fallthrough
	case "ne":
		if reslen != lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）不等于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "greaterthan":
		fallthrough
	case "gt":
		if reslen > lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "lessthan":
		fallthrough
	case "lt":
		if reslen < lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）小于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "gte":
		if reslen >= lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于等于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "lte":
		if reslen <= lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）小于等于实际（"+strconv.Itoa(reslen)+"）"))
			return errlist
		}
	case "wi":
		fallthrough
	case "within":
		//整体匹配
		if u2.SliceHas(strings.Split(explen, ","), strconv.Itoa(reslen), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望："+explen+"，实际："+strconv.Itoa(reslen)))
		}
	case "wo":
		fallthrough
	case "without":
		//整体不匹配
		if !u2.SliceHas(strings.Split(explen, ","), strconv.Itoa(reslen), false) {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望："+explen+"，实际："+strconv.Itoa(reslen)))
		}
	default:
		errlist = append(errlist, errors.New(key+"校验失败，数值校验未知校验规则："+action))
		return errlist
	}

}

// checkFloat 校验长度
// key 字段名称
// reslen 实际
// explen 期望
// action 校验规则
// errlist 错误列表
// 支持规则：leq/eq/neq/greaterthan/lessthan/gte/lte
func checkFloat(key string, reslen float64, explen string, action string, errlist []error) []error {
	if action == "between" || action == "bt" {
		lexp := strings.Split(explen, ",")
		if len(lexp) != 2 {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist

		}
		lexp1, err := strconv.ParseFloat(lexp[0], 64)
		if err != nil {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist
		}
		lexp2, err := strconv.ParseFloat(lexp[1], 64)
		if err != nil {
			errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
			return errlist
		}
		if reslen > lexp1 && reslen < lexp2 {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+"）"))
			return errlist
		}
	}

	lexp, err := strconv.ParseFloat(explen, 64)
	if err != nil {
		errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
		return errlist
	}
	switch action {
	case "leq":
		fallthrough
	case "eq":
		if reslen == lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）等于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
			return errlist
		}
	case "neq":
		fallthrough
	case "ne":
		if reslen != lexp {
			return errlist
		} else {
			return append(errlist, errors.New(key+"校验失败，期望（"+explen+"）不等于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
		}
	case "greaterthan":
		fallthrough
	case "gt":
		if reslen > lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
			return errlist
		}
	case "lessthan":
		fallthrough
	case "lt":
		if reslen < lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）小于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
			return errlist
		}
	case "gte":
		if reslen >= lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）大于等于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
			return errlist
		}
	case "lte":
		if reslen <= lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）小于等于实际（"+strconv.FormatFloat(reslen, 'f', 2, 64)+")"))
			return errlist
		}

	default:
		errlist = append(errlist, errors.New(key+"校验失败，浮点数未知校验规则："+action))
		return errlist
	}

}

// checkBool 校验
// key 字段名称
// reslen 实际
// explen 期望
// action 校验规则
// errlist 错误列表
// 支持规则：eq
func checkBool(key string, reslen bool, explen string, action string, errlist []error) []error {
	lexp, err := strconv.ParseBool(explen)
	if err != nil {
		errlist = append(errlist, errors.New(key+"校验失败，期望比较数值,当前长度值为："+explen))
		return errlist
	}
	switch action {
	case "eq":
		if reslen == lexp {
			return errlist
		} else {
			errlist = append(errlist, errors.New(key+"校验失败，期望（"+explen+"）等于实际（"+strconv.FormatBool(reslen)+"）"))
		}
	default:
		errlist = append(errlist, errors.New(key+"校验失败~，布尔值未知校验规则："+action))
		return errlist
	}
	return errlist
}
